﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;
using OpenComposite.EII.Repository;
using OpenComposite.Repository.Properties;
using OpenComposite.Base.Collections;
using System.ComponentModel;
using System.Diagnostics;
using OpenComposite.EII.Controls;

namespace OpenComposite.EII
{
	public class UsedByHierarchyTreeView : RepositoryHierarchyTreeView
	{

		#region getItemsOfRepositoryItem
		// Schema
		// getItemsOfType(Type item, bool deeper){
		//	get SearchableSortableBindingList of items using parameter item
		//	--- or ---
		//	get items of the parameter items properties
		//	add the items to the return value (using createTreeNode() / createTreeNodeArray(worker, ))
		// }

		protected override TreeNode[] getItemsOfNoun(BackgroundWorker worker, Noun item, bool deeper)
		{
			//if ( worker.CancellationPending ) return new TreeNode[] { };
			BindingListEx<BusinessObject> bobjects = Global.Data.GetBusinessObjectsOfNoun(item.ID);

			List<TreeNode> list = new List<TreeNode>();
			foreach ( BusinessObject bo in bobjects ) {
				list.Add(createTreeNode(worker, bo, deeper));
			}
			return list.ToArray();
		}

		protected override TreeNode[] getItemsOfBusinessObject(BackgroundWorker worker, BusinessObject item, bool deeper)
		{
			//if ( worker.CancellationPending ) return new TreeNode[] { };
			BindingListEx<Verb> verbs = Global.Data.GetVerbsOfBusinessObject(item.ID);
			BindingListEx<Repository.Workflow> workflows = Global.Data.GetWorkflowsOfBusinessObject(item.ID);
			BindingListEx<BusinessObject> parentBOs = Global.Data.GetParentBusinessObjects(item.ID);
			BindingListEx<LogicalWebMethod> lms = Global.Data.GetLogicalMethodsOfVerb(item.ID);
			BindingListEx<WorkflowMethod> wfM = Global.Data.GetWorkflowMethodOfBusinessObject(item.ID);
			BindingListEx<WorkflowField> wfF = Global.Data.GetWorkflowFieldOfBusinessObject(item.ID);
			BindingListEx<WorkflowEvent> wfE = Global.Data.GetWorkflowEventOfBusinessObject(item.ID);

			List<TreeNode> nodes = new List<TreeNode>();
			nodes.AddRange(createTreeNodeArray(worker, parentBOs, deeper));
			nodes.AddRange(createTreeNodeArray(worker, verbs, deeper));
			nodes.AddRange(createTreeNodeArray(worker, lms, deeper));
			nodes.AddRange(createTreeNodeArray(worker, workflows, deeper));
			nodes.AddRange(createTreeNodeArray(worker, wfM, deeper));
			nodes.AddRange(createTreeNodeArray(worker, wfF, deeper));
			nodes.AddRange(createTreeNodeArray(worker, wfE, deeper));

			return nodes.ToArray();
		}

		protected override TreeNode[] getItemsOfVerb(BackgroundWorker worker, Verb item, bool deeper)
		{
			//if ( worker.CancellationPending ) return new TreeNode[] { };
			BindingListEx<Repository.Workflow> workflows = Global.Data.GetWorkflowsOfVerb(item.ID);
			BindingListEx<LogicalWebMethod> lms = Global.Data.GetLogicalMethodsOfVerb(item.ID);
			List<TreeNode> nodes = new List<TreeNode>();
			if ( item.Capability != null ) {
				nodes.Add(createTreeNode(worker, item.Capability, deeper));
			}
			nodes.AddRange(createTreeNodeArray(worker, workflows, deeper));
			nodes.AddRange(createTreeNodeArray(worker, lms, deeper));

			return nodes.ToArray();
		}

		protected override TreeNode[] getItemsOfBusinessRule(BackgroundWorker worker, RepositoryBusinessRule item, bool deeper)
		{
			//if ( worker.CancellationPending ) return new TreeNode[] { };
			BindingListEx<Repository.Workflow> workflows = Global.Data.GetWorkflowsFromBusinessRule(item.ID);

			List<TreeNode> nodes = new List<TreeNode>();
			nodes.AddRange(createTreeNodeArray(worker, workflows, deeper));

			return nodes.ToArray();
		}

		protected override TreeNode[] getItemsOfLogicalMethod(BackgroundWorker worker, LogicalWebMethod item, bool deeper)
		{
			//if ( worker.CancellationPending ) return new TreeNode[] { };
			BindingListEx<Verb> verbs = Global.Data.GetVerbsOfLogicalMethod(item.ID);

			List<TreeNode> nodes = new List<TreeNode>();
			if ( item.WebMethod != null ) {
				nodes.Add(createTreeNode(worker, item.WebMethod, deeper));
			}
			if ( item.HumanActivity != null ) {
				nodes.Add(createTreeNode(worker, item.HumanActivity, deeper));
			}
			if ( item.EndpointRule != null ) {
				nodes.Add(createTreeNode(worker, item.EndpointRule, deeper));
			}
			nodes.AddRange(createTreeNodeArray(worker, verbs, deeper));

			return nodes.ToArray();
		}

		protected override TreeNode[] getItemsOfWebMethod(BackgroundWorker worker, WebMethod item, bool deeper)
		{
			//if ( worker.CancellationPending ) return new TreeNode[] { };
			BindingListEx<Verb> verbs = Global.Data.GetVerbsOfWebMethod(item.ID);

			List<TreeNode> nodes = new List<TreeNode>();
			if ( item.WebService != null ) {
				nodes.Add(createTreeNode(worker, item.WebService, deeper));
			}
			nodes.AddRange(createTreeNodeArray(worker, verbs, deeper));

			return nodes.ToArray();
		}

		protected override TreeNode[] getItemsOfWebService(BackgroundWorker worker, WebService item, bool deeper)
		{
			//if ( worker.CancellationPending ) return new TreeNode[] { };
			//SearchableSortableBindingList<WebMethod> webMethods = Global.Data.GetWebMethodsOfWebServices(item.ID);

			List<TreeNode> nodes = new List<TreeNode>();
			//nodes.AddRange(createTreeNodeArray(worker, webMethods, deeper));

			return nodes.ToArray();
		}

		protected override TreeNode[] getItemsOfHumanActivity(BackgroundWorker worker, Repository.HumanActivity item, bool deeper)
		{
			//if ( worker.CancellationPending ) return new TreeNode[] { };
			BindingListEx<LogicalWebMethod> lwms = Global.Data.GetLogicalWebMethodsOfHumanActivity(item.ID);

			List<TreeNode> nodes = new List<TreeNode>();
			nodes.AddRange(createTreeNodeArray(worker, lwms, deeper));

			return nodes.ToArray();
		}

		protected override TreeNode[] getItemsOfRuleConstants(BackgroundWorker worker, RuleConstant item, bool deeper)
		{
			//if ( worker.CancellationPending ) return new TreeNode[] { };
			BindingListEx<RepositoryBusinessRule> rules = Global.Data.GetBusinessRulesOfRuleConstant(item.ID);

			List<TreeNode> nodes = new List<TreeNode>();
			nodes.AddRange(createTreeNodeArray(worker, rules, deeper));

			return nodes.ToArray();
		}

		protected override TreeNode[] getItemsOfCapability(BackgroundWorker worker, ServiceModule item, bool deeper)
		{
			//if ( worker.CancellationPending ) return new TreeNode[] { };
			BindingListEx<Verb> verbs = item.GetVerbs();
			List<TreeNode> nodes = new List<TreeNode>();
			foreach ( Verb verb in verbs ) {
				BindingListEx<Repository.Workflow> workflows = Global.Data.GetWorkflowsOfVerb(verb.ID);
				nodes.AddRange(createTreeNodeArray(worker, workflows, deeper));
			}
			return nodes.ToArray();
		}

		protected override TreeNode[] getItemsOfWorkflow(BackgroundWorker worker, Repository.Workflow item, bool deeper)
		{
			//if ( worker.CancellationPending ) return new TreeNode[] { };
			List<TreeNode> nodes = new List<TreeNode>();

			if ( item.Capability != null ) {
				nodes.Add(createTreeNode(worker, item.Capability, deeper));
			}

			return nodes.ToArray();
		}
		#endregion

		#region [Async] getItemsOfRepositoryItem
		// Schema
		// getItemsOfTypeAsync(BackgroundWorker worker, Type item){
		//	--- do this for each Type using the parameter item ---
		//	CheckOrAddFolder(FolderType)
		//	create SearchableSortableBindingList of Items using parameter item
		//	--- or ---
		//	get items of the parameter items properties
		//	report progress to worker, 
		//		use TraverseAction.Add or TraverseAction.AddRange, 
		//		use the correct folder node (see enum FolderType for further information), 
		//		use createTreeNode() / createTreeNodeArray(worker, ) on the SearchableSortableBindingList
		//	--- optionally get items using using items (e.g. get items using BusinessObjects which are using a Noun) ---
		//	--- !!!use this with caution of endless loops!!! ---
		//	use getItemsOfTypeAsync(BackgroundWorker worker, ) for each item in the SearchableSortableBindingList
		// }

		protected override void getItemsOfNounAsync(BackgroundWorker worker, Noun item)
		{
			//if ( worker.CancellationPending ) return;
			bool deeper = true;

			//CheckOrAddFolder(FolderType.BusinessObjects);
			BindingListEx<BusinessObject> bobjects = Global.Data.GetBusinessObjectsOfNoun(item.ID);

			worker.ReportProgress(0, new WorkerState(TraverseAction.AddRange, _businessObjects, createTreeNodeArray(worker, bobjects, deeper)));

			//CheckOrAddFolder(FolderType.Rules);
			BindingListEx<RepositoryBusinessRule> rules = Global.Data.GetBusinessRulesOfNoun(item.ID);

			worker.ReportProgress(0, new WorkerState(TraverseAction.AddRange, _rules, createTreeNodeArray(worker, rules, deeper)));

			foreach ( BusinessObject bo in bobjects ) {
				getItemsOfBusinessObjectAsync(worker, bo);
			}
			foreach ( RepositoryBusinessRule rule in rules ) {
				getItemsOfBusinessRuleAsync(worker, rule);
			}

		}

		protected override void getItemsOfBusinessObjectAsync(BackgroundWorker worker, BusinessObject item)
		{
			//if ( worker.CancellationPending ) return;
			bool deeper = true;
			//CheckOrAddFolder(FolderType.BusinessObjects);
			BindingListEx<BusinessObject> parentBOs = Global.Data.GetParentBusinessObjects(item.ID);
			worker.ReportProgress(0, new WorkerState(TraverseAction.AddRange, _businessObjects, createTreeNodeArray(worker, parentBOs, deeper)));

			//CheckOrAddFolder(FolderType.Capabilities);
			BindingListEx<Verb> verbs = Global.Data.GetVerbsOfBusinessObject(item.ID);
			BindingListEx<Verb> nonDeletedVerbs = new BindingListEx<Verb>();
			foreach ( Verb v in verbs ) {
				if ( v.Capability == null || v.Capability.IsDeleted ) continue;
				nonDeletedVerbs.AddDistinct(v);
			}
			worker.ReportProgress(0, new WorkerState(TraverseAction.AddRange, _capabilities, createTreeNodeArray(worker, nonDeletedVerbs, deeper)));

			//CheckOrAddFolder(FolderType.Processes);
			BindingListEx<Repository.Workflow> workflows = Global.Data.GetWorkflowsOfBusinessObject(item.ID);
			worker.ReportProgress(0, new WorkerState(TraverseAction.AddRange, _processes, createTreeNodeArray(worker, workflows, deeper)));

			//CheckOrAddFolder(FolderType.LogicalMethods);
			BindingListEx<LogicalWebMethod> logMeths = Global.Data.GetLogicalMethodsOfBusinessObject(item.ID);
			worker.ReportProgress(0, new WorkerState(TraverseAction.AddRange, _logicalMethods, createTreeNodeArray(worker, logMeths, deeper)));

			//CheckOrAddFolder(FolderType.WorkflowInterface);
			BindingListEx<WorkflowMethod> wfM = Global.Data.GetWorkflowMethodOfBusinessObject(item.ID);
			worker.ReportProgress(0, new WorkerState(TraverseAction.AddRange, _workflowInterface, createTreeNodeArray(worker, wfM, deeper)));

			BindingListEx<WorkflowField> wfF = Global.Data.GetWorkflowFieldOfBusinessObject(item.ID);
			worker.ReportProgress(0, new WorkerState(TraverseAction.AddRange, _workflowInterface, createTreeNodeArray(worker, wfF, deeper)));

			BindingListEx<WorkflowEvent> wfE = Global.Data.GetWorkflowEventOfBusinessObject(item.ID);
			worker.ReportProgress(0, new WorkerState(TraverseAction.AddRange, _workflowInterface, createTreeNodeArray(worker, wfE, deeper)));

			foreach ( Verb verb in verbs ) {
				getItemsOfVerbAsync(worker, verb);
			}

			foreach ( BusinessObject bo in parentBOs ) {
				getItemsOfBusinessObjectAsync(worker, bo);
			}

			BindingListEx<Repository.Workflow> wfs = new BindingListEx<OpenComposite.EII.Repository.Workflow>();
			foreach ( WorkflowMethod wm in wfM ) {
				wfs.Add(wm.Workflow);
			}
			foreach ( WorkflowField wf in wfF ) {
				wfs.Add(wf.Workflow);
			}
			foreach ( WorkflowEvent we in wfE ) {
				wfs.Add(we.Workflow);
			}
			worker.ReportProgress(0, new WorkerState(TraverseAction.AddRange, _processes, createTreeNodeArray(worker, wfs, deeper)));
		}

		protected override void getItemsOfVerbAsync(BackgroundWorker worker, Verb item)
		{
			bool deeper = true;

			//CheckOrAddFolder(FolderType.Processes);
			BindingListEx<Repository.Workflow> workflows = Global.Data.GetWorkflowsOfVerb(item.ID);
			worker.ReportProgress(0, new WorkerState(TraverseAction.AddRange, _processes, createTreeNodeArray(worker, workflows, deeper)));

			//CheckOrAddFolder(FolderType.LogicalMethods);
			BindingListEx<LogicalWebMethod> lwms = Global.Data.GetLogicalMethodsOfVerb(item.ID);
			worker.ReportProgress(0, new WorkerState(TraverseAction.AddRange, _logicalMethods, createTreeNodeArray(worker, lwms, deeper)));
		}

		protected override void getItemsOfBusinessRuleAsync(BackgroundWorker worker, RepositoryBusinessRule item)
		{
			//if ( worker.CancellationPending ) return;
			bool deeper = true;

			//CheckOrAddFolder(FolderType.Processes);
			BindingListEx<Repository.Workflow> workflows = Global.Data.GetWorkflowsFromBusinessRule(item.ID);

			worker.ReportProgress(0, new WorkerState(TraverseAction.AddRange, _processes, createTreeNodeArray(worker, workflows, deeper)));

			// TODO: Get using workflows and business rules
		}

		protected override void getItemsOfLogicalMethodAsync(BackgroundWorker worker, LogicalWebMethod item)
		{
			//if ( worker.CancellationPending ) return;
			bool deeper = true;
			//CheckOrAddFolder(FolderType.Capabilities);
			BindingListEx<Verb> verbs = Global.Data.GetVerbsOfLogicalMethod(item.ID);
			worker.ReportProgress(0, new WorkerState(TraverseAction.AddRange, _capabilities, createTreeNodeArray(worker, verbs, deeper)));
			foreach ( Verb verb in verbs ) {
				getItemsOfVerbAsync(worker, verb);
			}

			//CheckOrAddFolder(FolderType.Rules);
			if ( item.EndpointRule != null ) {
				worker.ReportProgress(0, new WorkerState(TraverseAction.Add, _rules, createTreeNode(worker, item.EndpointRule, deeper)));
			}
			//CheckOrAddFolder(FolderType.HumanActivities);
			if ( item.HumanActivity != null ) {
				worker.ReportProgress(0, new WorkerState(TraverseAction.Add, _humanActivities, createTreeNode(worker, item.HumanActivity, deeper)));
			}
		}

		protected override void getItemsOfWebMethodAsync(BackgroundWorker worker, WebMethod item)
		{
			//if ( worker.CancellationPending ) return;
			bool deeper = true;
			//SearchableSortableBindingList<Verb> verbs = Global.Data.GetVerbsOfWebMethod(item.ID);
			//CheckOrAddFolder(FolderType.Capabilities);
			//worker.ReportProgress(0, new WorkerState(TraverseAction.AddRange, _capabilities, createTreeNodeArray(worker, verbs, deeper)));

			BindingListEx<LogicalWebMethod> lwms = Global.Data.GetLogicalWebMethodsOfWebMethod(item.ID);
			//CheckOrAddFolder(FolderType.LogicalMethods);
			worker.ReportProgress(0, new WorkerState(TraverseAction.AddRange, _logicalMethods, createTreeNodeArray(worker, lwms, deeper)));

			foreach ( LogicalWebMethod method in lwms ) {
				getItemsOfLogicalMethodAsync(worker, method);
			}

			if ( item.WebService != null ) {
				//CheckOrAddFolder(FolderType.WebServices);
				worker.ReportProgress(0, new WorkerState(TraverseAction.Add, _webservices, createTreeNode(worker, item.WebService, deeper)));
			}
		}

		protected override void getItemsOfWebServiceAsync(BackgroundWorker worker, WebService item)
		{
			//if ( worker.CancellationPending ) return;
			bool deeper = true;
			BindingListEx<WebMethod> methods = item.GetWebMethods();

			//CheckOrAddFolder(FolderType.LogicalMethods);
			foreach ( WebMethod method in methods ) {
				BindingListEx<LogicalWebMethod> lwms = Global.Data.GetLogicalWebMethodsOfWebMethod(method.ID);
				worker.ReportProgress(0, new WorkerState(TraverseAction.AddRange, _logicalMethods, createTreeNodeArray(worker, lwms, deeper)));
				foreach ( LogicalWebMethod logMeth in lwms ) {
					getItemsOfLogicalMethodAsync(worker, logMeth);
				}
			}

			//bool deeper = true;
			//string query = "SELECT v.* FROM verbs v, logical_webmethods lwm, webservices ws " +
			//    "WHERE v.log_wmeth_id = lwm.log_wmeth_id AND lwm.websvc_id = ws.websvc_id  AND ws.websvc_id = @websvc_id " +
			//    "AND v.is_deleted = 0 AND lwm.is_deleted = 0 AND ws.is_deleted = 0";
			//CheckOrAddFolder(FolderType.Capabilities);
			//Global.Data.GetLogicalWebMethods
			//worker.ReportProgress(0, new WorkerState(TraverseAction.AddRange, _capabilities, createTreeNodeArray(worker, verbs, deeper)));
		}

		protected override void getItemsOfHumanActivityAsync(BackgroundWorker worker, Repository.HumanActivity item)
		{
			//if ( worker.CancellationPending ) return;
			bool deeper = true;
			//CheckOrAddFolder(FolderType.LogicalMethods);
			BindingListEx<LogicalWebMethod> lwms = Global.Data.GetLogicalWebMethodsOfHumanActivity(item.ID);
			worker.ReportProgress(0, new WorkerState(TraverseAction.AddRange, _logicalMethods, createTreeNodeArray(worker, lwms, deeper)));
		}

		protected override void getItemsOfRuleConstantsAsync(BackgroundWorker worker, RuleConstant item)
		{
			//if ( worker.CancellationPending ) return;
			bool deeper = true;
			//CheckOrAddFolder(FolderType.Rules);
			BindingListEx<RepositoryBusinessRule> rules = Global.Data.GetBusinessRulesOfRuleConstant(item.ID);
			worker.ReportProgress(0, new WorkerState(TraverseAction.AddRange, _rules, createTreeNodeArray(worker, rules, deeper)));
		}

		protected override void getItemsOfCapabilityAsync(BackgroundWorker worker, ServiceModule item)
		{
			//if ( worker.CancellationPending ) return;
			bool deeper = true;
			//CheckOrAddFolder(FolderType.Processes);
			BindingListEx<Verb> verbs = item.GetVerbs();
			List<Repository.Workflow> workflows = new List<OpenComposite.EII.Repository.Workflow>();
			foreach ( Verb verb in verbs ) {
				worker.ReportProgress(0, new WorkerState(TraverseAction.AddRange, _processes, createTreeNodeArray(worker, Global.Data.GetWorkflowsOfVerb(verb.ID), deeper)));
			}
		}

		protected override void getItemsOfWorkflowAsync(BackgroundWorker worker, Repository.Workflow item)
		{
			//if ( worker.CancellationPending ) return;
			bool deeper = true;

			if ( item.Capability != null ) {
				//CheckOrAddFolder(FolderType.Capabilities);
				worker.ReportProgress(0, new WorkerState(TraverseAction.Add, _capabilities, createTreeNode(worker, item.Capability, deeper)));

				getItemsOfVerbAsync(worker, item.Capability);
			}
		}
		#endregion

	}
}